package boot

import (
	"context"
	"fmt"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gfile"
	"regexp"
	"strconv"
	"strings"
)

const (
	dbName      = "server-asset"
	sqlFilePath = "./database/db.sql"
)

func InitDb(ctx context.Context) {
	fmt.Println("初始化数据库...")
	InitDatabase(ctx)
}

func InitDatabase(ctx context.Context) {
	sqlContent := gfile.GetContents("./database/db.sql")
	if _, err := gdb.GetConfig("default").Exec(ctx, sqlContent); err != nil {
		panic(fmt.Sprintf("初始化数据库失败: %v", err))
	}

	// 第一步：检查并创建数据库
	if !isDatabaseExist(ctx) {
		fmt.Println("创建数据库！")
		createDatabase(ctx)
	}

	// 第二步：初始化表结构
	initTables(ctx)
}

// 检查数据库是否存在
func isDatabaseExist(ctx context.Context) bool {
	// 使用默认配置（不带数据库名）创建临时连接
	tempDb, err := createTempConnection(ctx, false)
	if err != nil {
		panic(fmt.Sprintf("创建临时连接失败: %v", err))
	}
	defer tempDb.Close(ctx)

	// 检查数据库存在性（添加错误处理细节）
	query := `SELECT COUNT(*) FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ?`
	result, err := tempDb.Query(ctx, query, dbName)
	if err != nil {
		return false
	}
	fmt.Printf("数据库 %s 存在状态: %t\n", dbName, result.Array())
	return result.Array()[0].Int() > 0
}

/**
 * 创建数据库
 */
func createDatabase(ctx context.Context) {
	tempDb, err := createTempConnection(ctx, false)
	if err != nil {
		panic(fmt.Sprintf("创建临时连接失败: %v", err))
	}
	defer tempDb.Close(ctx)

	query := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s`", dbName)
	_, err_r := tempDb.Query(ctx, query)
	if err_r != nil {
		panic(fmt.Sprintf("创建数据库失败: %v", err))
	}
	fmt.Printf("数据库 %s 创建成功\n", dbName)
}

func initTables(ctx context.Context) {
	// 1. 执行基础SQL
	executeSQLFile(ctx)
	fmt.Println("初始化完成")
	// 2. 自动迁移新增字段
	//autoMigrateTables(ctx)
}

/*
 * 创建临时连接（不带数据库名）
 */
func createTempConnection(ctx context.Context, isName bool) (gdb.DB, error) {
	// 获取原始配置
	originalConfig := g.Cfg().MustGet(ctx, "database.default").Map()

	// 转换为ConfigNode
	configNode := gdb.ConfigNode{
		Host: originalConfig["host"].(string),
		Port: originalConfig["port"].(string),
		User: originalConfig["user"].(string),
		Pass: originalConfig["pass"].(string),
		//Name: originalConfig["name"].(string),
		Type: originalConfig["type"].(string),
	}
	if isName {
		configNode = gdb.ConfigNode{
			Host: originalConfig["host"].(string),
			Port: originalConfig["port"].(string),
			User: originalConfig["user"].(string),
			Pass: originalConfig["pass"].(string),
			Name: originalConfig["name"].(string),
			Type: originalConfig["type"].(string),
		}
	}
	// 创建临时配置
	tempGroup := "temp_init"
	if err := gdb.AddConfigNode(tempGroup, configNode); err != nil {
		return nil, err
	}

	return gdb.Instance(tempGroup)
}

/**
 * 文件初始化
 */
func executeSQLFile(ctx context.Context) {
	tempDb, err := createTempConnection(ctx, true)
	if err != nil {
		panic(fmt.Sprintf("创建临时连接失败: %v", err))
	}
	defer tempDb.Close(ctx)
	sqlContent := gfile.GetContents("./database/db.sql")

	// 处理事务
	if err := tempDb.Transaction(ctx, func(ctx_c context.Context, tx gdb.TX) error {
		// 分割SQL语句（以分号+换行为分隔符）
		sqlStatements := parseSQLStatements(sqlContent)

		// 逐条执行
		for _, stmt := range sqlStatements {
			stmt = strings.TrimSpace(stmt)
			if stmt == "" {
				continue
			}
			//fmt.Println(stmt)
			if _, err := tx.ExecContext(ctx_c, stmt); err != nil {
				return fmt.Errorf("执行SQL失败: %s → %v", truncateString(stmt, 50), err)
			}
		}
		return nil
	}); err != nil {
		panic(fmt.Sprintf("初始化表结构失败: %v", err))
	}

	fmt.Println("SQL文件执行成功")
}

// parseSQLStatements 分割SQL语句
func parseSQLStatements(content string) []string {
	// 处理跨行语句（去除注释和空行）
	content = regexp.MustCompile(`(?m)--.*$`).ReplaceAllString(content, "") // 删除注释
	content = regexp.MustCompile(`\n+`).ReplaceAllString(content, "\n")     // 合并空行

	// 按分号分割（排除函数/过程内的分号）
	splitter := regexp.MustCompile(`;\s*\n`)
	return splitter.Split(content, -1)
}

// truncateString 截断长字符串用于错误提示
func truncateString(s string, maxLen int) string {
	if len(s) <= maxLen {
		return s
	}
	return s[:maxLen] + "..."
}

/**
 * 首字母大写
 */
func capitalizeFirstLetter(s string) string {
	if len(s) == 0 {
		return s
	}
	return strings.ToUpper(string(s[0])) + s[1:]
}

/**
 * 辅助函数（处理类型转换）
 */
func parsePort(port interface{}) int {
	switch v := port.(type) {
	case int:
		return v
	case string:
		if p, err := strconv.Atoi(v); err == nil {
			return p
		}
	}
	return 3306 // 默认值
}
